/*     */ package com.zimbra.cs.service.mail;
/*     */ 
/*     */ import com.google.common.io.Closeables;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.soap.Element;
/*     */ import com.zimbra.common.soap.MailConstants;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.filter.RuleManager;
/*     */ import com.zimbra.cs.index.SortBy;
/*     */ import com.zimbra.cs.index.ZimbraHit;
/*     */ import com.zimbra.cs.index.ZimbraQueryResults;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.MailboxIndex;
/*     */ import com.zimbra.cs.mailbox.OperationContext;
/*     */ import com.zimbra.soap.ZimbraSoapContext;
/*     */ import java.util.ArrayList;
/*     */ import java.util.EnumSet;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import org.apache.jsieve.parser.generated.Node;
/*     */ import org.apache.jsieve.parser.generated.ParseException;
/*     */ import org.dom4j.QName;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ApplyFilterRules
/*     */   extends MailDocumentHandler
/*     */ {
/*     */   public Element handle(Element request, Map<String, Object> context)
/*     */     throws ServiceException
/*     */   {
/*  50 */     ZimbraSoapContext zsc = getZimbraSoapContext(context);
/*  51 */     Account account = getRequestedAccount(zsc);
/*     */     
/*  53 */     if (!canAccessAccount(zsc, account)) {
/*  54 */       throw ServiceException.PERM_DENIED("cannot access account");
/*     */     }
/*     */     
/*  57 */     String fullScript = getRules(account);
/*  58 */     if (StringUtil.isNullOrEmpty(fullScript)) {
/*  59 */       throw ServiceException.INVALID_REQUEST("Account has no filter rules defined.", null);
/*     */     }
/*     */     
/*  62 */     List<Element> ruleElements = request.getElement("filterRules").listElements("filterRule");
/*     */     
/*  64 */     if (ruleElements.size() == 0) {
/*  65 */       String msg = String.format("No %s elements specified.", new Object[] { "filterRule" });
/*  66 */       throw ServiceException.INVALID_REQUEST(msg, null);
/*     */     }
/*     */     
/*     */ 
/*  70 */     StringBuilder buf = new StringBuilder();
/*  71 */     for (Element ruleEl : ruleElements) {
/*  72 */       String name = ruleEl.getAttribute("name");
/*  73 */       String singleRule = RuleManager.getRuleByName(fullScript, name);
/*  74 */       if (singleRule == null) {
/*  75 */         String msg = String.format("Could not find a rule named '%s'", new Object[] { name });
/*  76 */         throw ServiceException.INVALID_REQUEST(msg, null);
/*     */       }
/*  78 */       buf.append(singleRule).append("\n");
/*     */     }
/*  80 */     String partialScript = buf.toString();
/*  81 */     ZimbraLog.filter.debug("Applying partial script to existing messages: %s", new Object[] { partialScript });
/*  82 */     Node node = null;
/*     */     try {
/*  84 */       node = RuleManager.parse(partialScript);
/*     */     } catch (ParseException e) {
/*  86 */       throw ServiceException.FAILURE("Unable to parse Sieve script: " + partialScript, e);
/*     */     }
/*     */     
/*     */ 
/*  90 */     Element msgEl = request.getOptionalElement("m");
/*  91 */     String query = getElementText(request, "query");
/*  92 */     if ((msgEl != null) && (query != null)) {
/*  93 */       String msg = String.format("Cannot specify both %s and %s elements.", new Object[] { "m", "query" });
/*     */       
/*  95 */       throw ServiceException.INVALID_REQUEST(msg, null);
/*     */     }
/*     */     
/*  98 */     Mailbox mbox = getRequestedMailbox(zsc);
/*  99 */     List<Integer> messageIds = new ArrayList();
/* 100 */     List<Integer> affectedIds = new ArrayList();
/* 101 */     OperationContext octxt = getOperationContext(zsc, context);
/*     */     
/* 103 */     if (msgEl != null) {
/* 104 */       String[] ids = msgEl.getAttribute("ids").split(",");
/* 105 */       for (String id : ids) {
/* 106 */         messageIds.add(Integer.valueOf(id));
/*     */       }
/* 108 */     } else if (query != null) {
/* 109 */       ZimbraQueryResults results = null;
/*     */       try {
/* 111 */         results = mbox.index.search(octxt, query, EnumSet.of(MailItem.Type.MESSAGE), SortBy.NONE, Integer.MAX_VALUE);
/*     */         
/* 113 */         while (results.hasNext()) {
/* 114 */           ZimbraHit hit = results.getNext();
/* 115 */           messageIds.add(Integer.valueOf(hit.getItemId()));
/*     */         }
/*     */       } catch (Exception e) {
/* 118 */         String msg = String.format("Unable to run search for query: '%s'", new Object[] { query });
/* 119 */         throw ServiceException.INVALID_REQUEST(msg, e);
/*     */       } finally {
/* 121 */         Closeables.closeQuietly(results);
/*     */       }
/*     */     } else {
/* 124 */       String msg = String.format("Must specify either the %s or %s element.", new Object[] { "m", "query" });
/*     */       
/* 126 */       throw ServiceException.INVALID_REQUEST(msg, null);
/*     */     }
/*     */     
/* 129 */     int max = account.getFilterBatchSize();
/* 130 */     if (messageIds.size() > max) {
/* 131 */       throw ServiceException.INVALID_REQUEST("Attempted to apply filter rules to " + messageIds.size() + " messages, which exceeded the limit of " + max, null);
/*     */     }
/*     */     
/*     */ 
/* 135 */     ZimbraLog.filter.info("Applying filter rules to %s existing messages.", new Object[] { Integer.valueOf(messageIds.size()) });
/* 136 */     long sleepInterval = account.getFilterSleepInterval();
/*     */     
/*     */ 
/* 139 */     for (int i = 0; i < messageIds.size(); i++) {
/* 140 */       if ((i > 0) && (sleepInterval > 0L)) {
/*     */         try {
/* 142 */           Thread.sleep(sleepInterval);
/*     */         }
/*     */         catch (InterruptedException e) {}
/*     */       }
/*     */       
/* 147 */       int id = ((Integer)messageIds.get(i)).intValue();
/*     */       try {
/* 149 */         mbox.getMessageById(octxt, id);
/* 150 */         if (RuleManager.applyRulesToExistingMessage(octxt, mbox, id, node)) {
/* 151 */           affectedIds.add(Integer.valueOf(id));
/*     */         }
/*     */       }
/*     */       catch (MailServiceException.NoSuchItemException e) {
/* 155 */         ZimbraLog.filter.info("Skipping message %d: %s.", new Object[] { Integer.valueOf(id), e.toString() });
/*     */       } catch (ServiceException e) {
/* 157 */         ZimbraLog.filter.warn("Unable to filter message %d.", Integer.valueOf(id), e);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 162 */     Element response = zsc.createElement(getResponseElementName());
/* 163 */     if (affectedIds.size() > 0) {
/* 164 */       response.addElement("m").addAttribute("ids", StringUtil.join(",", affectedIds));
/*     */     }
/*     */     
/* 167 */     return response;
/*     */   }
/*     */   
/*     */   protected String getRules(Account account) {
/* 171 */     return RuleManager.getIncomingRules(account);
/*     */   }
/*     */   
/*     */   protected QName getResponseElementName() {
/* 175 */     return MailConstants.APPLY_FILTER_RULES_RESPONSE;
/*     */   }
/*     */   
/*     */   private String getElementText(Element parent, String childName) {
/* 179 */     Element child = parent.getOptionalElement(childName);
/* 180 */     if (child == null) {
/* 181 */       return null;
/*     */     }
/* 183 */     return child.getTextTrim();
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/mail/ApplyFilterRules.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */